home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
sozobon2.zoo
/
hcc
/
gen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-14
|
13KB
|
699 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* gen.c
*
* Generate code.
* Includes main routine and code generation for unary nodes
* and leafs.
*/
#include <stdio.h>
#include "param.h"
#include "bstok.h"
#include "tytok.h"
#include "flags.h"
#include "nodes.h"
#include "gen.h"
NODEP strsave;
int cctest;
static int reserve;
static int tmpused;
extern xflags[];
#define debug xflags['g'-'a']
#define FAIL 0
#define OKAY 1
#define isimmed(np) ((np)->g_flags & IMMEDID)
#define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
#define isdreg(np) ((np)->g_token == REGVAR && (np)->g_rno < AREG)
#define istdreg(np) ((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
int cookflags[] = {
0,
NOVAL_OK|CC_OK|IMMA_OK, /* FORSIDE */
IMMA_OK, /* FORPUSH */
CC_OK, /* FORCC */
IMMA_OK, /* FORIMA */
0, /* FORADR */
IMMA_OK, /* FORINIT */
0, /* IND0 */
0, /* RETSTRU */
};
genx(np, cookie)
register NODEP np;
{
extern nmerrors;
int rv;
extern NODE *blktab;
if (np == NULL) return;
if (nmerrors)
goto bad;
if (debug) {
printf("GEN enter");
printnode(np);
}
untype(np);
if (debug>1) {
printf("after UNTYPE");
printnode(np);
}
tmpused = 0;
gunk(np);
if (tmpused && tmpused > blktab->b_tsize)
blktab->b_tsize = tmpused;
if (debug > 1) {
printf("after gunk");
printnode(np);
}
order(np);
reserve = 0;
rv = eval(np, cookie);
if (rv == OKAY && debug) {
printf("GEN exit");
codeprint(np);
}
if (rv == OKAY)
rv = cookmon(np, cookie);
else
error("couldnt eval node");
freenode(np);
return rv;
bad:
freenode(np);
return FAIL;
}
eval(np, cookie)
register NODEP np;
{
int rv;
np->g_r1 = np->g_r2 = -1;
if (np == NULL) return FAIL;
switch (np->g_type) {
default:
rv = b_eval(np, cookie);
/* already did freetmps */
free1(np, np->n_left);
free1(np, np->n_right);
break;
case EV_LEFT:
rv = u_eval(np, cookie);
freetmps(np);
free1(np, np->n_left);
break;
case EV_NONE:
rv = l_eval(np);
break;
}
return rv;
}
u_eval(np, cookie)
register NODEP np;
{
int subcook = FORADR;
switch (np->g_token) {
case STAR:
subcook = FORIMA;
break;
case '!':
subcook = FORCC;
break;
}
if (eval(np->n_left, subcook) == FAIL)
return FAIL;
return u_sube(np, cookflags[cookie]);
}
u_sube(np, flags)
register NODEP np;
{
register NODEP lp = np->n_left;
long offs;
int i;
switch (np->g_token) {
case '.':
if (np->g_fldw)
return fldget(np, flags);
offs = np->g_offs;
inherit(np);
np->g_offs += offs;
return OKAY;
case STAR:
if (isimmed(lp)) {
inherit(np);
np->g_flags &= ~IMMEDID;
} else if (isareg(lp)) {
indir(np, lp->g_rno);
} else { /* NEED A temp */
if (lp->g_token == OREG && istemp(lp->g_rno))
i = lp->g_rno;
else
i = ralloc(AREG);
addcode(np, "\tmove.l\t<A,R0\n");
indir(np, i);
}
return OKAY;
case UNARY '&':
if (isimmed(lp))
warn("& ignored");
else if (lp->g_token == REGVAR)
return FAIL;
inherit(np);
np->g_flags |= IMMEDID;
if ((flags & IMMA_OK) == 0)
imm_oreg(np);
return OKAY;
case '~':
utemp(np);
addcode(np, "\tnot.S\tA\n");
cc_hack(np);
return OKAY;
case UNARY '-':
utemp(np);
addcode(np, "\tneg.S\tA\n");
cc_hack(np);
return OKAY;
case TCONV:
castgen(np);
return OKAY;
case PUSHER: /* must not be on left of assign or asn-op */
if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
istemp(lp->g_rno) == 0) {
inherit(np);
return OKAY;
}
if (lp->g_ty == ET_A)
strxpush(np);
else
addcode(np, "\tmove.S\t<A,-(sp)\n");
return OKAY;
case '(':
if (np->g_ty == ET_A) { /* struct returned */
frc_ral(AREG);
indir(np, AREG);
} else {
frc_ral(0);
retreg(np, 0);
}
addcode(np, "\tjsr\t<A\n");
return OKAY;
case DOUBLE '+':
holdcon(np);
inherit(np);
addcode(np, "\tadd.S\t#K,A\n");
cc_hack(np);
return OKAY;
case DOUBLE '-':
holdcon(np);
inherit(np);
addcode(np, "\tsub.S\t#K,A\n");
cc_hack(np);
return OKAY;
case POSTINC:
if ((flags & NOVAL_OK) == 0) {
i = ralloc(0);
retreg(np, i);
addcode(np, "\tmove.S\t<A,A\n");
}
addcode(np, "\tadd.S\t#O,<A\n");
return OKAY;
case POSTDEC:
if ((flags & NOVAL_OK) == 0) {
i = ralloc(0);
retreg(np, i);
addcode(np, "\tmove.S\t<A,A\n");
}
addcode(np, "\tsub.S\t#O,<A\n");
return OKAY;
case CMPBR:
i = ralloc(0);
retreg(np, i);
addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
cc_hack(np);
return OKAY;
case '!':
if (flags & CC_OK) {
if (iscc(lp)) {
i = cctok(lp);
i = (i&1) ? i+1 : i-1; /* reverse truth */
} else {
i = B_EQ;
addcode(np, "<Q");
}
np->g_token = i + BR_TOK;
} else {
if (istdreg(lp))
i = lp->g_rno;
else
i = ralloc(0);
retreg(np, i);
if (iscc(lp)) {
addcode(np, "<EA\n\tand.w\t#1,A\n");
} else {
addcode(np, "<Q");
addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
}
}
return OKAY;
default:
printf("Weird u_eval %s ", np->n_name);
return FAIL;
}
}
holdcon(np)
NODEP np;
{
np->g_bsize = np->g_offs;
}
retreg(np, rno)
NODEP np;
{
np->g_token = REGVAR;
np->g_rno = rno;
}
indir(np, rno)
register NODEP np;
{
np->g_token = OREG;
np->g_offs = 0;
np->g_rno = rno;
}
inherit(np)
register NODEP np;
{
NODEP lp = np->n_left;
np->g_token = lp->g_token;
np->g_offs = lp->g_offs;
np->g_rno = lp->g_rno;
np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
}
cookmon(np, cookie)
register NODEP np;
{
extern FILE *output;
if (np == NULL) return FAIL;
switch (cookie) {
case FORCC:
if (iscc(np)) {
outcode(np);
cctest = cctok(np);
} else {
if (np->g_token == ICON && isimmed(np)) {
cctest = np->g_offs ? B_YES : B_NO;
return OKAY;
}
outcode(np);
outsub("Q", np);
cctest = B_NE;
}
return OKAY;
case FORINIT:
if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
out_a(np, output);
return OKAY;
}
error("bad INIT expr");
return FAIL;
case IND0:
outcode(np);
if (np->g_token != REGVAR ||
np->g_rno != 0)
if (np->g_token == ICON && np->g_offs == 0 &&
isimmed(np))
outsub("\tclr.S\td0\n", np);
else
outsub("\tmove.S\tA,d0\n", np);
return OKAY;
case RETSTRU:
freetmps(np);
strret(np);
outcode(np);
return OKAY;
}
outcode(np);
return OKAY;
}
anycode(np)
register NODEP np;
{
if (np->g_code)
return 1;
switch (np->g_type) {
case EV_NONE:
return 0;
case EV_LEFT:
return anycode(np->n_left);
case EV_RIGHT:
return anycode(np->n_right);
case EV_LR:
case EV_RL:
return anycode(np->n_left) || anycode(np->n_right);
}
}
l_eval(np)
register NODEP np;
{
int l1;
switch (np->g_token) {
case ID:
switch (np->g_sc) {
default: /* EXTERN or HERE */
np->g_token = ONAME;
np->g_offs = 0;
if (np->n_name[0] != '%')
nnmins(np, "_");
else /* hack for inline name */
strcpy(np->n_name, &np->n_name[1]);
return OKAY; /* dont free n_nmx */
case K_STATIC:
sprintf(np->n_name, "L%d", (int)np->g_offs);
np->g_offs = 0;
np->g_token = ONAME;
break;
case K_AUTO:
np->g_rno = FRAMEP;
np->g_token = OREG;
break;
case K_REGISTER:
np->g_token = REGVAR;
break;
}
if (np->n_nmx) {
freenode(np->n_nmx);
np->n_nmx = NULL;
}
return OKAY;
case ICON:
np->g_flags |= IMMEDID;
return OKAY;
case FCON